import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;


public class Main  {
//	public static SharedMessageQueue msg[] = new SharedMessageQueue()[peerCount-1];
//	public static CountDownLatch countDown = new CountDownLatch(peerCount-1);
	
	public static void main(String[] args) {
		if(args.length == 0){
			System.out.println("No peerID given!");
			System.exit(0);
		}
		PeerData.setPeerID(Integer.parseInt(args[0]));
		//File Handling
		int peerInfo[][] = null;
		String peerInfoHostNames[]=null;
		// Initialization Code for reading file
		/*
		 * read System.properties into parameters
		 * start machines
		 */
		//Load the properties file
		PeerData peerData = new PeerData();
		try{
			Properties prop = new Properties();
			InputStream is = new FileInputStream("C://Users//Sirisha//workspace//BitTorrentCN//src//common.cfg");
			prop.load(is);
			//Read the properties file parameters...
			peerData.setNumberOfPreferredNeighbors(Integer.parseInt(prop.getProperty("NumberOfPreferredNeighbors")));
			peerData.setUnchokingInterval(Integer.parseInt(prop.getProperty("UnchokingInterval")));
			peerData.setOptimisticUnchokingInterval(Integer.parseInt(prop.getProperty("OptimisticUnchokingInterval")));
			String fileName = prop.getProperty("FileName");
			peerData.setFileSize(Integer.parseInt(prop.getProperty("FileSize"))); // check if can be parsed to long 
			peerData.setPieceSize(Integer.parseInt(prop.getProperty("PieceSize")));
			
			// Read peerdata.cfg
			FileReader fr = new FileReader("C://Users//Sirisha//workspace//BitTorrentCN//src//PeerInfo.cfg");
	        BufferedReader br = new BufferedReader(fr);
		    String read;
		    StringTokenizer readTokenizer;
		    int numberOfPeers = 0;
		    
		    //read number of peers (lines) in file
		    br.mark(9999999);
	        while((read = br.readLine()) != null) {
		    	numberOfPeers++;
		    }
	        peerData.peerCount = numberOfPeers;
		    //go to the start of file
		    br.reset();
		    peerInfo = new int[numberOfPeers][4];
		    peerInfoHostNames = new String[numberOfPeers];
		    //read the parameters into peerInfo
		    int index = 0;
		    while((read = br.readLine()) != null) {
		    	readTokenizer = new StringTokenizer(read);
		    	peerInfo[index][0] = Integer.parseInt(readTokenizer.nextToken());
		    	peerInfo[index][1] = -1; // indicates read string instead
		    	peerInfoHostNames[index] = readTokenizer.nextToken();
		    	peerInfo[index][2] = Integer.parseInt(readTokenizer.nextToken());
		    	peerInfo[index][3] = Integer.parseInt(readTokenizer.nextToken());
		    	index++;
		    }
		    System.out.println("NO Error reading cfg");
			
			
		} catch (Exception e){
			System.out.println("Error reading config files!");
			e.printStackTrace();
		}
		//File handling end.
		
		Socket soc = null;
		ServerSocket sersoc = null;
		int portNumber = -1;
		for(int i=0;i<peerInfo.length;i++){
			if(peerInfo[i][0] == PeerData.getPeerID()){
				portNumber = peerInfo[i][2]; 				
			}
		}
		if(portNumber == -1){
			System.out.println("Wrong input in peerinfo.cfg");
			System.exit(0);
		}
		try {
			sersoc = new ServerSocket(portNumber);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ObjectInputStream objIn = null;
		ObjectOutputStream objOut = null;
		Thread receive[] = new Thread[peerData.peerCount];
		Thread send[] = new Thread[peerData.peerCount];
		//Send connection:
		try{
		for(int i=0;peerInfo[i]!=null;i++){
			if(peerInfo[i][0] < PeerData.getPeerID()){
				soc = new Socket(peerInfoHostNames[i], peerInfo[i][2]); //Sending to peers whose ID<peerID
				
			}
			else if(peerInfo[i][0] > PeerData.getPeerID()){
				soc = sersoc.accept(); ////Receiving from peers whose ID>peerID
			}
			else{
				continue;
			}
			/************ generate Streams ************************/
			objIn = new ObjectInputStream(soc.getInputStream());
			objOut = new ObjectOutputStream(soc.getOutputStream());
			
			/************ receiver thread from this peer to all peers ********/
			receive[i] = new ReceiverThread(objIn);
			receive[i].start();
			
			/*********** Sender thread from this peer to all peer  *********/
			send[i] = new SenderThread(objOut);		
			send[i].start();
			
		}
		}catch(Exception e){
			
		}
		
		/*********** Common thread for calculating prefered neighbours irrespective of peer connected to *********/
		Thread prefNeig = new PrefNeighbourCalThread();
		prefNeig.start();
	}
}
